using System;
using System.Collections.Generic;
using System.Text;
using XLETL.Common;
using XLETL.Model;
using System.Linq;
using System.Xml.Linq;
using System.IO;

namespace XLETL.BLL
{
    	/// <summary>
	/// A business component to manage schedule objects
	/// </summary>
    public class Schedule
    {
    
		/// <summary>
		/// Save Task Process Schedule into task data storage
		/// </summary>
		/// <param name="taskId"></param>
		/// <param name="schedule">Schedule business entity that contain week days set to
		/// true/false, boolean daily, weekly, and time.</param>
		public bool SaveTaskProcessSchedule(ScheduleInfo schedule, bool isNew){

            if (schedule == null)
            {
                throw new ArgumentNullException("Parameter \"schedule\" is null");
            }

            XElement schedules = new XElement(ScheduleInfo.SCHEDULES);

            if (File.Exists(GlobalCache.SCHEDULE_STORAGE_PATH))
            {
                // load all schedules
                XElement existingSchedules = XElement.Load(GlobalCache.SCHEDULE_STORAGE_PATH);

                IEnumerable<XElement> singleSchedule = null;
                Guid scheduleId = schedule.ID;

                // only update 
                /*if (!schedule.ID.Equals(Guid.Empty))
                {
                    scheduleId = schedule.ID;

                    //obtain a single user
                    singleSchedule = (from targetSchedule in existingSchedules.Elements(ScheduleInfo.SCHEDULE)
                                      where ((Guid)targetSchedule.Element(ScheduleInfo.SCHEDULE_ID)).Equals(scheduleId)
                                      select targetSchedule);
                }
                else
                {
                    scheduleId = Guid.NewGuid();
                }*/

                if (!isNew)
                {
                  //obtain a single user
                  singleSchedule = (from targetSchedule in existingSchedules.Elements(ScheduleInfo.SCHEDULE)
                                    where ((Guid)targetSchedule.Element(ScheduleInfo.SCHEDULE_ID)).Equals(scheduleId)
                                    select targetSchedule);
                }

                XElement newSchedule = new XElement(ScheduleInfo.SCHEDULE,
               new XElement(ScheduleInfo.SCHEDULE_ID, scheduleId),
               new XElement(ScheduleInfo.TASK_ID, schedule.TaskID),
               new XElement(ScheduleInfo.DAYILY, schedule.Dayly),
               new XElement(ScheduleInfo.WEEKLY, schedule.Weekly),
               new XElement(ScheduleInfo.WEEKDAYS,
               (schedule.WeekDays != null) ? 
               (from day in schedule.WeekDays select new XElement(ScheduleInfo.WEEKDAY, day)) : null),
               //new XElement(ScheduleInfo.MON, schedule.Mon),
               //new XElement(ScheduleInfo.TUE, schedule.Tue),
               //new XElement(ScheduleInfo.WEN, schedule.Wen),
               //new XElement(ScheduleInfo.THU, schedule.Thu),
               //new XElement(ScheduleInfo.FRI, schedule.Fri),
               //new XElement(ScheduleInfo.SAT, schedule.Sat),
               //new XElement(ScheduleInfo.SUN, schedule.Sun),
               new XElement(ScheduleInfo.HOUR, schedule.Hour),
               new XElement(ScheduleInfo.MIN, schedule.Min)
               );

                if (singleSchedule != null)
                {
                    //update schedule, should only be 1
                    foreach (XElement xe in singleSchedule)
                    {
                        //xe.Remove();
                        xe.ReplaceWith(newSchedule);
                    }

                    existingSchedules.Save(GlobalCache.SCHEDULE_STORAGE_PATH);

                }
                else
                {
                    schedules.Add(existingSchedules.Elements(ScheduleInfo.SCHEDULE));
                    schedules.Add(newSchedule);
                    schedules.Save(GlobalCache.SCHEDULE_STORAGE_PATH);
                }

                return true;
            }
            else
            {
                return false;
            }
		}

        /// <summary>
        /// Get full list of schedules
        /// </summary>
        public List<ScheduleInfo> GetScheduleList()
        {
            if (File.Exists(GlobalCache.SCHEDULE_STORAGE_PATH))
            {
                XElement existingSchedules = XElement.Load(GlobalCache.SCHEDULE_STORAGE_PATH);

                var schedules = from schedElement in existingSchedules.Elements(ScheduleInfo.SCHEDULE)
                                select new ScheduleInfo
                          {
                            TaskID = (Guid)schedElement.Element(ScheduleInfo.TASK_ID),
                            ID = (Guid)schedElement.Element(ScheduleInfo.SCHEDULE_ID),
                            Dayly = (bool)schedElement.Element(ScheduleInfo.DAYILY),
                            Weekly = (bool)schedElement.Element(ScheduleInfo.WEEKLY),
                            //Mon = (bool)schedElement.Element(ScheduleInfo.MON),
                            //Tue = (bool)schedElement.Element(ScheduleInfo.TUE),
                            //Wen = (bool)schedElement.Element(ScheduleInfo.WEN),
                            //Thu = (bool)schedElement.Element(ScheduleInfo.THU),
                            //Fri = (bool)schedElement.Element(ScheduleInfo.FRI),
                            //Sat = (bool)schedElement.Element(ScheduleInfo.SAT),
                            //Sun = (bool)schedElement.Element(ScheduleInfo.SUN),
                            Hour = (int)schedElement.Element(ScheduleInfo.HOUR),
                            Min = (int)schedElement.Element(ScheduleInfo.MIN),
                            WeekDays = (from dayEl in schedElement.Descendants(ScheduleInfo.WEEKDAY) select dayEl.Value).ToArray<string>()
                          };
                return schedules.ToList<ScheduleInfo>();
            }
            else return new List<ScheduleInfo>();
        }

        /// <summary>
        /// Get schedule for a particular task
        /// </summary>
        public ScheduleInfo GetSchedule(Guid taskID)
        {
          if (File.Exists(GlobalCache.SCHEDULE_STORAGE_PATH))
          {
            XElement existingSchedules = XElement.Load(GlobalCache.SCHEDULE_STORAGE_PATH);

            var schedules = from schedElement in existingSchedules.Elements(ScheduleInfo.SCHEDULE)
                            let taskid = (Guid)schedElement.Element(ScheduleInfo.TASK_ID)
                            where taskid.Equals(taskID) 
                            select new ScheduleInfo
                            {
                              TaskID = (Guid)schedElement.Element(ScheduleInfo.TASK_ID),
                              ID = (Guid)schedElement.Element(ScheduleInfo.SCHEDULE_ID),
                              Dayly = (bool)schedElement.Element(ScheduleInfo.DAYILY),
                              Weekly = (bool)schedElement.Element(ScheduleInfo.WEEKLY),
                              //Mon = (bool)schedElement.Element(ScheduleInfo.MON),
                              //Tue = (bool)schedElement.Element(ScheduleInfo.TUE),
                              //Wen = (bool)schedElement.Element(ScheduleInfo.WEN),
                              //Thu = (bool)schedElement.Element(ScheduleInfo.THU),
                              //Fri = (bool)schedElement.Element(ScheduleInfo.FRI),
                              //Sat = (bool)schedElement.Element(ScheduleInfo.SAT),
                              //Sun = (bool)schedElement.Element(ScheduleInfo.SUN),
                              Hour = (int)schedElement.Element(ScheduleInfo.HOUR),
                              Min = (int)schedElement.Element(ScheduleInfo.MIN),
                              WeekDays = (from dayEl in schedElement.Descendants(ScheduleInfo.WEEKDAY) select dayEl.Value).ToArray<string>()
                            };
            List<ScheduleInfo> ls = schedules.ToList<ScheduleInfo>();
            if (ls.Count > 0)
            {
              return ls[0];
            }
            else { return null; }            
          }
          else return null;
        }
}
}
